package com.auicyh.tylb.utils;

import android.content.Context;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.util.Log;


import com.auicyh.tylb.R;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.lang.reflect.Field;
import java.nio.channels.FileChannel;

/**
 * 作者：  Ocean 2017/6/6 17:24
 * 功能：  文件处理工具类
 * Q Q：
 * 修改：
 * @author Ocean
 */

public class FileUtils {

    /**
     * 快速文件复制
     * @param source 源文件
     * @param dest   目标文件
     */
    public static void copyFile(String source, String dest) {
        FileChannel inputChannel = null;
        FileChannel outputChannel = null;
        try {
            inputChannel = new FileInputStream(source).getChannel();
            outputChannel = new FileOutputStream(dest).getChannel();
            outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
        } catch (Exception e) {
            Log.e("IO", e.getMessage());
        } finally {
            try {
                if (inputChannel != null) {
                    inputChannel.close();
                }
                if (outputChannel != null) {
                    outputChannel.close();
                }
            } catch (IOException e) {
                Log.e("TAG", e.getMessage());
            }
        }
    }

    /**
     * 复制Assets中的文件到指定目录
     * @param inputStream 输入流
     * @param destPath    目标文件路径
     * @param destName    目标文件名字
     */
    public static void copyAssets(InputStream inputStream, String destPath, String destName) {
        FileOutputStream fileOutputStream = null;
        // 创建文件夹
        File file = getFile(destPath, destName);
        try {
            fileOutputStream = new FileOutputStream(file);
            byte[] buf = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buf)) > 0) {
                fileOutputStream.write(buf, 0, bytesRead);
            }
        } catch (IOException e) {
            // LogUtil.e(e.getMessage());
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (fileOutputStream != null) {
                    fileOutputStream.flush();
                    fileOutputStream.close();
                }
            } catch (IOException e) {
                // LogUtil.e(e.getMessage());
            }
        }

    }

    /**
     * 向文件中写入数据
     * @param path      文件路径
     * @param fileName  文件全名
     * @param message   写入的信息
     * @param append    写入方式是否追加
     * @param isBigFile 是否时大文件的写入 建议true 否则回出现中文乱码问题
     */
    public static void writeFile(String path, String fileName, String message, boolean append, boolean isBigFile) {
        File file = getFile(path, fileName);
        if (isBigFile) {
            writeFile(file, message, append);
        } else {
            // 可能回出现中文乱码
            writeLittleFile(file, message, append);
        }
    }

    /**
     * 文件读取
     * @param path     路径
     * @param fileName 文件全名
     * @param tag      读完一行后是否加标签
     * @return 读取内容
     */
    @NonNull
    public static String readFile(@NonNull String path, String fileName, String tag) {
        File file = new File(path, fileName);
        if (file.exists()) {
            return readFile(file, tag);
        } else {
            return "-1";
        }
    }

    /**
     * writeFile是一个带缓冲写方法，用于大量文件的写入
     * 用于把内容或者信息写入到SD卡中的文件中去，
     * @param file    file
     * @param message 要写入的内容信息
     * @param append  写入方式true追加
     */
    private static void writeFile(File file, String message, boolean append) {
        // 通过FileOutStream设置文件的写入方式
        FileOutputStream fileOutputStream = null;
        // 通过OutputStreamWrite 把字符流转换成字节流
        OutputStreamWriter outputStreamWriter = null;
        // 通过BufferedWrite进行写入操作，避免频繁的进行磁盘的读写
        BufferedWriter bufferedWriter = null;
        try {
            fileOutputStream = new FileOutputStream(file, append);
            outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8");
            bufferedWriter = new BufferedWriter(outputStreamWriter);
            bufferedWriter.write(message);
            // 把内容一次性写入文件
            bufferedWriter.flush();
        } catch (Exception e) {
            Log.e("文件写入异常", e.getMessage());
        } finally {
            try {
                if (bufferedWriter != null) {
                    bufferedWriter.close();
                }
                if (outputStreamWriter != null) {
                    outputStreamWriter.close();
                }
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }
            } catch (IOException e) {
                Log.e("TAG", e.getMessage());

            }

        }
    }

    /**
     * @param file    file
     * @param message 内容信息
     * @param append  写入方式
     */
    private static void writeLittleFile(File file, String message, boolean append) {
        FileWriter fileWriter = null;
        try {
            fileWriter = new FileWriter(file, append);
            fileWriter.write(message);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (fileWriter != null) {
                    fileWriter.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * readFile读取文件内容  大
     * @param file file
     * @return 返回读到的字符串
     */
    private static String readFile(File file, String tag) {
        // 带缓冲的读
        BufferedReader bufferedReader = null;
        StringBuilder stringBuilder = new StringBuilder();
        try {
            // InputStreamReader 转换流把字节流转换成字符, FileInputStream文件读取输入流
            bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                stringBuilder.append(line).append(tag);
            }
        } catch (IOException e) {
            e.printStackTrace();
            return "-1";
        } finally {
            try {
                if (bufferedReader != null) {
                    bufferedReader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return stringBuilder.toString();
    }

    /**
     * 这个方法用于判断SD的状态，若SD卡是处于安装状态或者SD卡无法移动这返回true。
     * @return 返回SD状态，不可移动或者被安装返回true
     */
    public static boolean isSDCardExist() {
        // 获取SD卡的的状态，是否被安装 mounted
        String state = Environment.getExternalStorageState();
        // 判断SD卡是否可移除
        boolean removable = Environment.isExternalStorageRemovable();
        return Environment.MEDIA_MOUNTED.equals(state) || !removable;
    }

    /**
     * 这个方法用于获取磁盘的根目录，
     * 如果SD存在者返回SD的根目录，否则返回内部的文件储存地址
     * @return path
     * DIRECTORY_MUSIC 音乐目录
     * DIRECTORY_PODCASTS 博客目录
     * DIRECTORY_RINGTONES 铃声
     * DIRECTORY_ALARMS 闹钟警报
     * DIRECTORY_NOTIFICATIONS 通知
     * DIRECTORY_PICTURES 图片
     * DIRECTORY_MOVIES 电影
     * DIRECTORY_DOWNLOADS 下载
     * DIRECTORY_DCIM
     * DIRECTORY_DOCUMENTS 文档
     */
    public static String getDiskDir(Context context) {
        return context.getFilesDir().getPath();
    }

    /**
     * 返回数据库目录
     * @param context context
     * @return 数据库目录
     */
    public static String getDataBaseDir(Context context) {
        return context.getDatabasePath("db").getPath();
    }

    /**
     * 存在SD卡返回外部的下载目录
     * @return 系统下载目录
     */
    public static String getDownloads(Context context) {
        String path;
        if (isSDCardExist()) {
            // 获取外部SD卡的绝对路径
            path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
        } else {
            // 获取内部的文件储存地址
            path = context.getFilesDir().getPath();
        }
        return path;
    }

    /**
     * 获取外部文件目录
     * @param context context
     * @return 返回文件目录
     */
    public static String getFileDir(Context context) {
        String path;
        if (isSDCardExist()) {
            // 获取外部SD卡的绝对路径 getExternalFilesDir
            path = Environment.getExternalStorageDirectory().getAbsolutePath();
        } else {
            // 获取内部的文件储存地址
            path = context.getFilesDir().getPath();
        }
        return path;
    }

    /**
     * 获取folderName目录,如果folderName目录不存在，返回根目录地址
     * @param context    context
     * @param folderName 文件夹名
     * @return path
     */
    public static String getFilePdfDir(Context context, String folderName) {
        String path;
        if (isSDCardExist()) {
            // 获取外部SD卡的绝对路径 getExternalFilesDir
            File file = context.getExternalFilesDir(folderName);
            if (file != null) {
                path = file.getPath();
            } else {
                path = Environment.getExternalStorageDirectory().getAbsolutePath();
            }
        } else {
            // 获取内部的文件储存地址
            path = context.getFilesDir().getPath();
        }
        return path;
    }


    /**
     * 创建File文件夹
     * @param path     path
     * @param fileName fileName
     * @return file
     */
    @NonNull
    public static File getFile(String path, String fileName) {
        // 创建文件夹
        File folder = new File(path);
        if (!folder.exists()) {
            // noinspection ResultOfMethodCallIgnored
            folder.mkdirs();
        }
        return new File(folder, fileName);
    }

    /**
     * 判断文件是否存在
     * @param filePathName 文件路径 + 文件名
     * @return 文件存在返回真
     */
    public static boolean isFile(String filePathName) {
        File file = new File(filePathName);
        return file.exists();
    }

    /**
     * 获取String资源ID
     * @param context 上下文
     * @param resName 名字
     *                http://blog.csdn.net/jenly121/article/details/51564229
     * @return 资源ID
     */
    public static int getStringResId(Context context, String resName) {
        return context.getResources().getIdentifier(resName, "string", context.getPackageName());
    }

    /**
     * 获取Color资源ID
     * @param context 上下文
     * @param resName 名字
     *                http://blog.csdn.net/jenly121/article/details/51564229
     * @return 资源ID
     */
    public static int getColorResId(Context context, String resName) {
        return context.getResources().getIdentifier(resName, "color", context.getPackageName());
    }

    /**
     * 根据名字获取图片资源ID
     * @param filename 文件名
     * @return 资源ID
     */
    public static int getImageRes(String filename) {
        if (StringUtils.isStrNull(filename)) {
            return R.mipmap.tylb_launcher;
        }
        Class draw = R.drawable.class;
        try {
            // 返回Field对象
            Field field = draw.getField(filename);
            return field.getInt(filename);
        } catch (Exception e) {
            return R.mipmap.tylb_launcher;
        }
    }

    /**
     * 读取assets中的文件 流程
     * FileUtils.assetsRed("json/MainHome.json", this);
     * @param fileName 文件名
     * @param context  context
     * @return 读取的内容
     */
    public static String assetsRed(String fileName, Context context) {
        // 输入流对象
        InputStream inputStream;
        // 缓存流对象
        BufferedReader bufferedReader = null;
        StringBuilder stringBuilder = new StringBuilder();
        try {
            // getAssets方法返回通过输入流对象
            inputStream = context.getAssets().open(fileName);
            // InputStreamReader 实现字节流到字符流的转换
            bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String line = "";
            while ((line = bufferedReader.readLine()) != null) {
                stringBuilder.append(line);
            }
        } catch (IOException e) {
            // LogUtil.e(e.getMessage());
        } finally {
            try {
                if (bufferedReader != null) {
                    bufferedReader.close();
                }
            } catch (IOException e) {
                //  LogUtil.e(e.getMessage().trim());
            }
        }
        return stringBuilder.toString();
    }

    /**
     * 删除文件
     * @param strPath  路径
     * @param endsWith 后缀
     */
    public static void deleteFile(String strPath, String endsWith) {
        File dir = new File(strPath);
        // 该文件目录下文件全部放入数组
        File[] files = dir.listFiles();
        if (files != null) {
            for (File file : files) {
                String fileName = file.getName();
                // 判断是文件还是文件夹
                if (file.isDirectory()) {
                    // 获取文件绝对路径
                    deleteFile(file.getAbsolutePath(), endsWith);
                } else if (fileName.endsWith(endsWith)) {
                    // 判断文件名是否以endsWith结尾
                    // String strFileName = file.getAbsolutePath();
                    File file1 = new File(strPath + "/" + fileName);
                    if (file1.exists()) {
                        //noinspection ResultOfMethodCallIgnored
                        file1.delete();
                    }
                }
            }
        }
    }
}
